package com.jeesite.modules.dp.service.order;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

import com.jeesite.common.config.Global;
import com.jeesite.common.lang.StringUtils;
import com.jeesite.modules.enums.DpRecordTypeEnum;
import com.jeesite.modules.enums.OrderTypeEnum;
import com.jeesite.modules.dp.service.user.ExtendUserService;
import com.jeesite.modules.utils.UrlUtils;
import org.apache.commons.collections.CollectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.github.binarywang.wxpay.bean.request.WxPayUnifiedOrderRequest;
import com.github.binarywang.wxpay.bean.result.WxPayUnifiedOrderResult;
import com.github.binarywang.wxpay.exception.WxPayException;
import com.github.binarywang.wxpay.service.WxPayService;
import com.jeesite.common.entity.Page;
import com.jeesite.common.lang.DateUtils;
import com.jeesite.common.service.CrudService;
import com.jeesite.modules.dp.dao.order.DpOrderDao;
import com.jeesite.modules.dp.entity.chatai.DpChatai;
import com.jeesite.modules.dp.entity.kccode.DpKechengcode;
import com.jeesite.modules.dp.entity.kcgoumai.DpKcgoumai;
import com.jeesite.modules.dp.entity.order.DpOrder;
import com.jeesite.modules.dp.entity.orderdetail.DpOrderdetail;
import com.jeesite.modules.dp.entity.vipinfo.DpVipinfo;
import com.jeesite.modules.dp.entity.yqrecord.DpYqrecord;
import com.jeesite.modules.dp.service.chatai.DpChataiService;
import com.jeesite.modules.dp.service.kccode.DpKechengcodeService;
import com.jeesite.modules.dp.service.kcgoumai.DpKcgoumaiService;
import com.jeesite.modules.dp.service.kecheng.DpKechengService;
import com.jeesite.modules.dp.service.orderdetail.DpOrderdetailService;
import com.jeesite.modules.dp.service.vipinfo.DpVipinfoService;
import com.jeesite.modules.dp.service.yqrecord.DpYqrecordService;
import com.jeesite.modules.sys.entity.User;
import com.jeesite.modules.sys.service.UserService;
import com.jeesite.modules.sys.utils.UserUtils;
import com.jeesite.modules.wxpay.WxPayConfiguration;

/**
 * 订单管理Service
 *
 * @author hancing
 * @version 2024-12-06
 */
@Service
public class DpOrderService extends CrudService<DpOrderDao, DpOrder> {

    private WxPayService wxPayService;

    @Autowired
    private DpOrderdetailService dpOrderdetailService;

    @Autowired
    private DpVipinfoService dpVipinfoService;

    @Autowired
    private DpYqrecordService dpYqrecordService;

    @Autowired
    private UserService userService;

    @Autowired
    private DpKechengService dpKechengService;

    @Autowired
    private DpKechengcodeService dpKechengcodeService;

    @Autowired
    private DpKcgoumaiService dpKcgoumaiService;

    @Autowired
    private DpChataiService dpChataiService;

    @Autowired
    private ExtendUserService extendUserService;

    @Value("${domain.path}")
    private String domainPath;

    @Value("${domain.ip}")
    private String domainIp;

    @Autowired
    private Environment env;

    private final Logger log = LoggerFactory.getLogger(DpOrderService.class);

    /**
     * 获取单条数据
     *
     * @param dpOrder
     * @return
     */
    @Override
    public DpOrder get(DpOrder dpOrder) {
        return super.get(dpOrder);
    }

    /**
     * 查询分页数据
     *
     * @param dpOrder 查询条件
     * @param dpOrder page 分页对象
     * @return
     */
    @Override
    public Page<DpOrder> findPage(DpOrder dpOrder) {
        return super.findPage(dpOrder);
    }

    /**
     * 查询列表数据
     *
     * @param dpOrder
     * @return
     */
    @Override
    public List<DpOrder> findList(DpOrder dpOrder) {
        return super.findList(dpOrder);
    }

    /**
     * 保存数据（插入或更新）
     *
     * @param dpOrder
     */
    @Override
    @Transactional
    public void save(DpOrder dpOrder) {
        super.save(dpOrder);
    }

    public void updateOutPayNo(String id, String outPayNo) {
        dao.updateOutPayNo(id, outPayNo);
    }

    private String generateOrderno(String orderId, String orderType) {
        String ordernoBefore = null;
        if (OrderTypeEnum.VIP_MEMBER.getType().equals(orderType)) {
            ordernoBefore = "MEMBER_";
        } else if (OrderTypeEnum.KC.getType().equals(orderType)) {
            ordernoBefore = "VIDEO_";
        } else {
            ordernoBefore = "CHAT_";
        }
        return ordernoBefore + orderId;
    }

    /**
     * 创建微信订单
     *
     * @param id         订单id
     * @param outTradeNo 订单编号
     * @param title      订单名称
     * @param amount     金额(元)
     * @throws WxPayException 调用异常
     */
    private WxPayBundleBean createWxPayOrder(String id, String outTradeNo,
                                             String title, int amount) throws WxPayException {
        // 模拟订单下单之类的操作
        if (wxPayService == null) {
            wxPayService = WxPayConfiguration.wxService();
        }
        Date expireDate = DateUtils.addSeconds(new Date(),
                Integer.parseInt(Global.getConfig("wxpay.expire.seconds", "300")));
        WxPayUnifiedOrderRequest request = new WxPayUnifiedOrderRequest();
        request.setOutTradeNo(outTradeNo); // 商户订单号
        request.setBody(title); // 商品描述
        request.setTotalFee(amount); // 订单总金额，单位为分
        request.setTradeType("NATIVE"); // 交易类型为Native
        request.setNotifyUrl(UrlUtils.joinUrl(domainPath, "js/wx/notify/scanpay"));
        request.setProductId(id);
        request.setDeviceInfo("WEB");
        request.setTimeExpire(DateUtils.formatDate(expireDate, "yyyyMMddHHmmss"));
        request.setSpbillCreateIp(domainIp.replaceAll("/", ""));
        return new WxPayBundleBean(request, wxPayService.unifiedOrder(request));
    }

    private synchronized DpKechengcode checkKcKucun(DpOrder dpOrder, String kcid) {
        DpKechengcode limit1Canuse = dpKechengcodeService.getLimit1Canuse(kcid);
        if (limit1Canuse == null) {
            dpOrder.setCreateok("0");
            dpOrder.setCreateerrmsg("课程激活码库存不足");
            return null;
        }
        return limit1Canuse;
    }

    private synchronized void lockKcKucun(DpOrder dpOrder, List<DpKechengcode> kcCodes) {
        List<DpKechengcode> lockedCodes = new ArrayList<>();
        for (DpKechengcode kcCode : kcCodes) {
            dpKechengcodeService.lockKcCode(kcCode.getId(), dpOrder.getUserno(), dpOrder.getId());
        }
    }

    @Transactional
    public synchronized DpOrder saveThenReturn(DpOrder dpOrder) {
        dpOrder.setUserno(UserUtils.getUser().getLoginCode());
        dpOrder.setOutpayno("");
        // 第一步，如果是购买课程，要检查激活码是否充足，并锁定激活码
        List<DpKechengcode> unUsedKcs = new ArrayList<>();
        if (OrderTypeEnum.KC.getType().equals(dpOrder.getOrdertype())) {
            for (DpOrderdetail detail : dpOrder.getOrderdetails()) {
                DpKechengcode unUsedKc = checkKcKucun(dpOrder, detail.getTypeid());
                if ("0".equals(dpOrder.getCreateok())) {
                    return dpOrder;
                }
                unUsedKcs.add(unUsedKc);
            }
        }

        super.save(dpOrder);

        String outno = generateOrderno(dpOrder.getId(), dpOrder.getOrdertype());
        dpOrder.setOutpayno(outno);
        updateOutPayNo(dpOrder.getId(), dpOrder.getOutpayno());

        // 更新订单详情的订单id
        for (DpOrderdetail detail : dpOrder.getOrderdetails()) {
            detail.setIsNewRecord(true);
            detail.setOrderid(dpOrder.getId());
            dpOrderdetailService.save(detail);
        }

        // 锁定课程编号库存
        lockKcKucun(dpOrder, unUsedKcs);

        // 判断是否需要下单,微信金额是否大于0
        if (dpOrder.getWxjiner() > 0) {
            try {

                WxPayBundleBean result = createWxPayOrder(dpOrder.getId(), outno,
                        dpOrder.getTitle(), (int) (dpOrder.getWxjiner() * 100));
                String timeExpire = result.request().getTimeExpire();
                dpOrder.setCodeurl(result.result().getCodeURL());
                dpOrder.setCodeurltime(new Date(System.currentTimeMillis()));
                dpOrder.setWxPayExpireTime(timeExpire.substring(0, 4) + "-" + timeExpire.substring(4, 6)
                        + "-" + timeExpire.substring(6, 8) + " " + timeExpire.substring(8, 10)
                        + ":" + timeExpire.substring(10, 12) + ":" + timeExpire.substring(12, 14));
                dpOrder.setCreateok("1");
                dpOrder.setFrontorderstatus(1);
                super.update(dpOrder);
                log.info("创建微信支付订单成功，订单类型: {} 订单号(out_trade_no): {}, 金额: {}, ",
                        OrderTypeEnum.getOfType(dpOrder.getOrdertype()).getName(), outno, dpOrder.getWxjiner() + "元");
            } catch (WxPayException e) {
                log.info("创建微信支付订单失败，订单类型: {} 订单号(out_trade_no): {}, 金额: {}, ",
                        OrderTypeEnum.getOfType(dpOrder.getOrdertype()).getName(), outno, dpOrder.getWxjiner() + "元");
                log.error("创建微信支付订单失败,errMsg: {}", e.getMessage(), e);
                dpOrder.setCreateok("0");
                // 释放被锁定的code
                for (DpKechengcode lockedCode : unUsedKcs) {
                    dpKechengcodeService.unLockKcCode(lockedCode.getId());
                }
            }
        } else {
            super.update(dpOrder);
            // 直接扣款，并触发订单完成结果
            dpOrder.setFrontorderstatus(2);
            doOrderPaySuccess(dpOrder.getId());
        }

        return dpOrder;
    }

    public DpOrder findByOutpayno(String outpayNo) {
        DpOrder entity = new DpOrder();
        entity.setOutpayno(outpayNo);
        List<DpOrder> list = findList(entity);
        return CollectionUtils.isEmpty(list) ? null : list.getFirst();
    }

    @Transactional
    public synchronized void doOrderPaySuccess(String orderid) {
        DpOrder dpOrder = super.get(orderid);
        if (dpOrder == null || "1".equals(dpOrder.getIswxpay())) {
            // 防止重复处理
            return;
        }
        try {
            List<DpOrderdetail> details = dpOrderdetailService.findByOrderId(orderid);
            for (DpOrderdetail detail : details) {
                if (OrderTypeEnum.VIP_MEMBER.getType().equals(dpOrder.getOrdertype())) {
                    // 处理会员购买事宜
                    DpVipinfo dpVipinfo = dpVipinfoService.get(detail.getTypeid());

                    // 增加会员日期
                    User user = extendUserService.getUserByLoginCode(dpOrder.getUserno());
                    Date addbasedate = extendUserService.getUserVipBaseTime(user);

                    Date newDateDays = switch (dpVipinfo.getViptimeunit()) {
                        case "1" -> DateUtils.addDays(addbasedate, dpVipinfo.getVipdaylong().intValue());
                        case "2" -> DateUtils.addWeeks(addbasedate, dpVipinfo.getVipdaylong().intValue());
                        case "3" -> DateUtils.addMonths(addbasedate, dpVipinfo.getVipdaylong().intValue());
                        default -> DateUtils.addYears(addbasedate, dpVipinfo.getVipdaylong().intValue());
                    };
                    dao.setUserExtendD1(dpOrder.getUserno(), newDateDays);
                    String timeUnitName = DpVipinfoService.VipTimeUnitEnum.getNameByUnit(dpVipinfo.getViptimeunit());
                    log.info("购买VIP会员订单，用户：{}, 购买时长: {}, 会员到期日: {}",
                            user.getLoginCode(), dpVipinfo.getVipdaylong() + timeUnitName,
                            DateUtils.formatDateTime(newDateDays));
                    // 更新缓存
                    if (UserUtils.getUser() != null) {
                        User cacheUser = UserUtils.getUser();
                        if (cacheUser.getExtend() == null) {
                            cacheUser.setExtend(user.getExtend());
                            cacheUser.getExtend().setExtendD1(newDateDays);
                        }
                    }

                } else if (OrderTypeEnum.KC.getType().equals(dpOrder.getOrdertype())) {

                    DpKechengcode kechengcode = dpKechengcodeService.findOrderCodes(dpOrder.getId());
                    if (kechengcode != null) {
                        log.info("购买课程，用户：{}, 订单id：{}, 课程code: {}", dpOrder.getUserno(), dpOrder.getId(), kechengcode.getKccode());
                        DpKcgoumai mai = new DpKcgoumai();
                        mai.setIsNewRecord(true);
                        mai.setKcid(kechengcode.getKcid());
                        mai.setKccode(kechengcode.getKccode());
                        mai.setUno(kechengcode.getUno());
                        mai.setOrderid(dpOrder.getId());
                        dpKcgoumaiService.save(mai);

                        // 处理课程购买事宜,将记录放到购课表，设置订单id的codestatus
                        dpKechengcodeService.setOrderIdUsed(dpOrder.getId());

                        // 更新课程已售出数量
                        dpKechengService.updaterealsell(detail.getTypeid());

                        log.info("购买课程，用户：{}, 订单id：{}, 课程code: {} - success", dpOrder.getUserno(), dpOrder.getId(), kechengcode.getKccode());

                        String vipGiftTime = Global.getConfig("dp.buykecheng.viptime");
                        if (!StringUtils.isBlank(vipGiftTime) && Integer.parseInt(vipGiftTime) > 0) {
                            User user = extendUserService.getUserByLoginCode(dpOrder.getUserno());
                            Date addbasedate = extendUserService.getUserVipBaseTime(user);
                            dao.setUserExtendD1(dpOrder.getUserno(),
                                    DateUtils.addMonths(addbasedate, Integer.parseInt(vipGiftTime)));

                            log.info("购买课程, 用户: {}, 赠送会员: {}", dpOrder.getUserno(), vipGiftTime + "月");
                        }
                    }
                } else {
                    // 处理聊天包购买
                    DpChatai dpai = dpChataiService.get(detail.getTypeid());
                    dao.addUserExtendI1(dpOrder.getUserno(), dpai.getCount().intValue());
                    log.info("购买聊天包, 用户: {}", dpOrder.getUserno());
                }
            }

            // 设置订单已经支付
            dao.setPayStatus(orderid, "1");
            // 减少权益金
            if (dpOrder.getDikoujiner() > 0) {
                dao.jianUserExtendF1(dpOrder.getUserno(), dpOrder.getDikoujiner());
                // 生成权益金使用记录
                DpYqrecord dpYqrecord = new DpYqrecord();
                dpYqrecord.setIsNewRecord(true);
                dpYqrecord.setQyj(0 - dpOrder.getDikoujiner());
                dpYqrecord.setYqr(dpOrder.getUserno());
                dpYqrecord.setQyjtype(DpRecordTypeEnum.ORDER_DK.getType());
                dpYqrecord.setQyjtitle("订单:" + dpOrder.getOutpayno() + "抵扣");
                dpYqrecordService.save(dpYqrecord);
            }

            String backMoneyOrderNs = Global.getConfig("dp.register.backmoney.orderns");
            String backMoneyRate = Global.getConfig("dp.register.backmoney.rate");

            if (!StringUtils.isBlank(backMoneyRate) && !StringUtils.isBlank(backMoneyOrderNs)) {
                double dbackMoneyRate = Double.parseDouble(backMoneyRate);
                int ibackMoneyOrderNs = Integer.parseInt(backMoneyOrderNs);
                // 判断用户是否是邀请码注册或存在邀请码,判断订单是否是前3笔订单
                if (dpOrder.getWxjiner() > 0 && dao.orderListMore0(dpOrder.getUserno()) < ibackMoneyOrderNs + 1) {
                    // 需要判断是否需要返现，查询订单用户是否是被邀请的
                    DpYqrecord yqr = dpYqrecordService.getUserTjr(dpOrder.getUserno());
                    // 金额最低0.01元
                    double fanxianAmount = Math.max(dpOrder.getWxjiner() * dbackMoneyRate, 0.01);
                    if ("dev".equals(env.getActiveProfiles()[0])) {
                        fanxianAmount = 0.03;
                    }
                    if (yqr != null) {
                        // 添加双方订单金额的10%
                        dpYqrecordService.addOrderFanxian(yqr.getYqr(), dpOrder.getUserno(),
                                fanxianAmount, dpOrder.getOrdertype());
                        log.info("邀请用户返现，返现人: [{}],[{}], 返现金额: {}", yqr.getYqr(), dpOrder.getUserno(), fanxianAmount);
                    }
                }
            }
        } catch (Exception e) {
            log.error("订单结果处理失败, errMsg: {}", e.getMessage(), e);
        }
    }

    public void payOrder(String id) {

        DpOrder dpOrder = get(id);
        // 模拟订单下单之类的操作
        if (wxPayService == null) {
            wxPayService = WxPayConfiguration.wxService();
        }

        WxPayUnifiedOrderRequest request = new WxPayUnifiedOrderRequest();
        request.setOutTradeNo(dpOrder.getId()); // 商户订单号
        request.setBody("Native支付测试"); // 商品描述
        request.setTotalFee(1); // 订单总金额，单位为分
        // request.setOpenid(openId); // 用户的openid
        request.setTradeType("Native"); // 交易类型为Native

        try {
            WxPayUnifiedOrderResult result = wxPayService.unifiedOrder(request);

            String codeurl = result.getCodeURL();

            System.out.println("codeurl===" + codeurl);
        } catch (WxPayException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

    /**
     * 更新状态
     *
     * @param dpOrder
     */
    @Override
    @Transactional
    public void updateStatus(DpOrder dpOrder) {
        super.updateStatus(dpOrder);
    }

    /**
     * 删除数据
     *
     * @param dpOrder
     */
    @Override
    @Transactional
    public void delete(DpOrder dpOrder) {
        super.delete(dpOrder);
    }

}